﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using CloudPms.Domain.Interface;

namespace CloudPms.Domain.Repository
{
    public abstract class RepositoryBase<T> :IRepository<T> where T :class,new()
    {
        private DbContext GetContext(string hotelId)
        {
            return DbContextService.GetDbContext(hotelId, typeof(T));
        }

        #region implemented IRepository

        /// <summary>
        /// Create a Entity , not e;
        /// </summary>
        /// <param name="hotelId"></param>
        /// <returns></returns>
        public T Create(string hotelId)
        {
            using (DbContext context = GetContext(hotelId))
            {
                return context.Set<T>().Create();
            }
        }

        public virtual T Update(string hotelId, T entity)
        {
            using (DbContext context = GetContext(hotelId))
            {
                context.Set<T>().Attach(entity);

                context.Entry(entity).State = EntityState.Modified;
                
                context.SaveChanges();
                
            }
            return entity;
        }

        public virtual T Insert(string hotelId,T entity)
        {
            //try
            //{
                using (DbContext context = GetContext(hotelId))
                {
                    context.Set<T>().Add(entity);
                    context.Entry(entity).State = EntityState.Added;
                    context.SaveChanges();
                }
            //}
            //catch (System.Data.Entity.Validation.DbEntityValidationException error)
            //{
            //    throw error;
            //}
            return entity;
        }

        public void Delete(string hotelId,T entity)
        {
            using (DbContext context = GetContext(hotelId))
            {
                context.Set<T>().Attach(entity);
                context.Set<T>().Remove(entity);
                context.SaveChanges();
            }
        }

        public T Get(string hotelId, params object[] keyValues)
        {
            if (!ParamsIsValid(keyValues))
            {
                throw new ArgumentNullException("Entity Key's Value is not Null");
            }

            using (DbContext context = GetContext(hotelId))
            {
                return context.Set<T>().Find(keyValues);
            }
        }

        public T Get(string hotelId, Expression<Func<T, bool>> exp)
        {
            using (DbContext context = GetContext(hotelId))
            {
                return context.Set<T>().FirstOrDefault(exp);
            }  
        }

        public List<T> GetAll(string hotelId)
        {
            using (DbContext context = GetContext(hotelId)) 
            {
                return context.Set<T>().ToList();
            }
            
        }

        public virtual void BatchInsert(string hotelId, IEnumerable<T> entities)
        {
            using (DbContext context = GetContext(hotelId))
            {
                foreach (var entity in entities)
                {
                    context.Set<T>().Add(entity);

                    context.Entry(entity).State = EntityState.Added;
                }
                //try
                //{
                    context.SaveChanges();
                //}catch (Exception error)
                //}catch (System.Data.Entity.Validation.DbEntityValidationException error)
                //{
                //    throw error;
                //}

            }
        }

        public virtual void BatchUpdate(string hotelId, IEnumerable<T> entities)
        {
            using(DbContext context=GetContext(hotelId))
            {
                foreach (var entity in entities)
                {
                    context.Set<T>().Attach(entity);

                    context.Entry(entity).State = EntityState.Modified;
                }

                context.SaveChanges();
            }
        }

        public void BatchDelete(string hotelId,IEnumerable<T> entities)
        {
            using(var context=GetContext(hotelId))
            {
                foreach (var entity in entities)
                {
                    context.Set<T>().Attach(entity);

                    //强制EF相信entity需要删除
                    context.Entry(entity).State = EntityState.Deleted;

                    context.Set<T>().Remove(entity);
                }

                context.SaveChanges();
            }
            
        }

        public List<T> BatchGet(string hotelId, Expression<Func<T, bool>> exp)
        {
            using (DbContext context = GetContext(hotelId)) 
            {
                return context.Set<T>().Where(exp).ToList();
            }            
        }

        #endregion

        /// <summary>
        /// 传参数据验证
        /// </summary>
        /// <param name="keyValues"></param>
        /// <returns></returns>
        private bool ParamsIsValid(object[] keyValues)
        {
            if(keyValues!=null)
            {
                return keyValues.All(value => value != null);
            }
            return false;
        }
        
    }
}
